/******************************************************************************
 * Student Name: Ofri Keidar
 * Exercise Name: Ex2
 * File Description: Class LecturerLinkedList's interface
 ******************************************************************************/

#ifndef LECTURERLINKEDLIST_H_
#define LECTURERLINKEDLIST_H_

#include "Lecturer.h"
#define ID_ERROR_VAL -1 // value to indicate error in id attribute
#define NAME_ERROR_VAL "ERROR" // value to indicate error in name attribute
using namespace std;

class LecturerLinkedList {

private:
	class Node {

		private:
			/***************************************************************************************
			 * function name: Node(const Node& node)
			 * The Input: Node to be copied
			 * The output: None
			 * The Function operation: The copy constructor is an empty-implementation
			 * 			               because node objects should not be sent to functions by value
			 ***************************************************************************************/
			Node(const Node& node): m_lecturerData(node.m_lecturerData) {}

		public:
			Lecturer* const m_lecturerData; // pointer to lecturer data
			Node* m_prevNode; // pointer no previous node
			Node* m_nextNode; // pointer to next node
			int m_index; // node index in linked list

			/***************************************************************************************
			 * function name: Node (Lecturer* const studentToPoint)
			 * The Input: Lecturer data to point at
			 * The output: None
			 * The Function operation: Creates a new node pointing to given lecturer
			 ***************************************************************************************/
			Node (Lecturer* const LecturerToPoint);

			/****************************************************************************************
			 * function name: ~Node()
			 * The Input: None
			 * The output: None
			 * The Function operation: Destructs node object
			 ***************************************************************************************/
			~Node();


			/****************************************************************************************
			 * function name: setIndex(const int newIndex)
			 * The Input: New index for node
			 * The output: None
			 * The Function operation: Sets index attribute as given value
			 ***************************************************************************************/
			void setIndex(const int newIndex) {m_index = newIndex;}
	};

	Node* m_headDummy; // pointer to first node on list
	Node* m_tailDummy; // pointer to last node on list
	Node* m_currentNode; // // node pointer that the user can change the node that it points at at get it's data

	/***************************************************************************************
	 * function name: LecturerLinkedList(const LecturerLinkedList& list)
	 * The Input: List to be copied
	 * The output: None
	 * The Function operation: The copy constructor is private and an empty-implementation
	 * 			               because student linked list objects should not be sent to
	 * 			               functions by value
	 ***************************************************************************************/
	LecturerLinkedList(const LecturerLinkedList& list) {}

	/***************************************************************************************
	 * function name: findPlace(const Lecturer& newLecturer)
	 * The Input: Pointer to lecturer to add
	 * The output: Node pointer to which the new lecturer should be linked.
	 * 			   If a lecturer with new student's id already exists, NULL is returned
	 * The Function operation: The method checks if a lecturer with the new studet's id already
	 * 			               exists. If no such lecturer was found, the method returns a
	 * 			               node pointer which before it new lecturer will be linked.
	 * 			               Method does not change lest object
	 ***************************************************************************************/
	Node* findPlace(const Lecturer& newLecturer) const;

	/***************************************************************************************
	 * function name: internalAdd(Lecturer& newStudent, Node* before)
	 * The Input: Pointer to lecturer to be added and a pointer to the node where the new
	 * 	          lecturer will be linked
	 * The output: None
	 * The Function operation: The method creates a new node pointing to the new lecturer
	 * 			               and links the new node in the given location to the list
	 ***************************************************************************************/
	void internalAdd(Lecturer& newLecturer, Node* before);

public:
	/***************************************************************************************
	 * function name: LecturerLinkedList()
	 * The Input: None
	 * The output: None
	 * The Function operation: Creates a new lecturer linked list
	 ***************************************************************************************/
	LecturerLinkedList();

	/***************************************************************************************
	 * function name: ~LecturerLinkedList()
	 * The Input: None
	 * The output: None
	 * The Function operation: Deletes the lecturer linked list and the pointed data
	 ***************************************************************************************/
	~LecturerLinkedList();

	/***************************************************************************************
	 * function name: addNode(Lecturer* newLecturer)
	 * The Input: Pointer to lecturer to be added
	 * The output: True if lecturer was added, False if not
	 * The Function operation: If there is already a lecturer with the new lecturer's id,
	 * 			               lecturer is not added.
	 * 			               Otherwise, it adds the lecturer and keeps the list sorted
	 * 			               from lowest id value to highest
	 ***************************************************************************************/
	bool addNode(Lecturer* val);

	/***************************************************************************************
	 * function name: initCurrent()
	 * The Input: None
	 * The output: None
	 * The Function operation: Sets current node pointer to list's head
	 ***************************************************************************************/
	void initCurrent() {m_currentNode = m_headDummy;}

	/***************************************************************************************
	 * function name: incrmntCurrent()
	 * The Input: None
	 * The output: False if end is reached, True if not
	 * The Function operation: Increments current node pointer. If points at lists end
	 * 			               returned value is False, otherwise True
	 ***************************************************************************************/
	bool incrmntCurrent();

	/***************************************************************************************
	 * function name: getCurrentID()
	 * The Input: None
	 * The output: Id of lecturer which current node pointer points at.
	 * 	           If current node points at no lecturer, ID_ERROR_VAL is returned
	 * The Function operation: Checks if lecturer pointer is NULL. If so, returned ID_ERROR_VAL,
	 *			               otherwise returns the id. The method does not change the object
	 ***************************************************************************************/
	int getCurrentID() const;

	/***************************************************************************************
	 * function name: getCurrentName()
	 * The Input: None
	 * The output: Name of lecturer which current node pointer points at.
	 * 	           If current node points at no lecturer, NAME_ERROR_VAL is returned
	 * The Function operation: Checks if lecturer pointer is NULL. If so, returned NAME_ERROR_VAL,
	 *			               otherwise returns the name. The method does not change the object
	 ***************************************************************************************/
	string getCurrentName() const;

	/***************************************************************************************
	 * function name: searchByKey(const int key)
	 * The Input: Id to look for
	 * The output: Pointer to lecturer whose id matches given value. If no such lecturer
	 * 	           exists, NULL is returned.
	 * The Function operation: Scans list- if a match is found, a pointer to this lecturer
	 * 			               is returned. If not, NULL is returned. Method does not change
	 * 			               list object or given key
	 ***************************************************************************************/
	Lecturer* searchByKey(const int key) const;

	/***************************************************************************************
	 * function name: searchByIndex(const int index)
	 * The Input: Index to look for
	 * The output: Pointer to lecturer whose index in list matches given value. If no such
	 * 	           lecturer exists, NULL is returned.
	 * The Function operation: Scans list- if a match is found, a pointer to this lecturer
	 * 			               is returned. If not, NULL is returned. Method does not change
	 *                         list object or given index
	 ***************************************************************************************/
	Lecturer* searchByIndex(const int index) const;
};

#endif
